package com.chenyitun.cloudsystem.aspect;

import com.google.common.collect.Lists;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 数据过滤处理
 *
 * @author ruoyi
 */
@Aspect
@Component
public class DataScopeAspect {

    /**
     * 全部数据权限
     */
    public static final String DATA_SCOPE_ALL = "1";

    /**
     * 自定数据权限
     */
    public static final String DATA_SCOPE_CUSTOM = "2";

    /**
     * 数据权限过滤关键字
     */
    public static final String DATA_SCOPE = "dataScope";


    @Autowired
    private RoleService roleService;
    @Autowired
    private DeptService deptService;

    // 配置织入点
    @Pointcut("@annotation(com.bootdo.common.annotation.DataScope)")
    public void dataScopePointCut() {
    }

    @Before("dataScopePointCut()")
    public void doBefore(JoinPoint point) throws Throwable {
        handleDataScope(point);
    }

    protected void handleDataScope(final JoinPoint joinPoint) {
        // 获得注解
        DataScope controllerDataScope = getAnnotationLog(joinPoint);
        if (controllerDataScope == null) {
            return;
        }
        // 获取当前的用户
        User currentUser = ShiroUtils.getUser();
        if (currentUser != null) {
            Map<String, Object> params = (Map<String, Object>) joinPoint.getArgs()[0];
            params.put(DATA_SCOPE, "");
            // 如果是超级管理员，则不过滤数据
//            currentUser.getBaseParams().put("dataScope" , "");
            if (currentUser.getUserId() != 1l) {
                Dept dept = deptService.get(currentUser.getDeptId());
                if (dept != null) {
                    currentUser.setDept(dept);
                    List<Role> roleList = roleService.listByUserId(currentUser.getUserId());
                    if (roleList != null && roleList.size() > 0) {
                        currentUser.setRoleList(roleList);
                        dataScopeFilter(params, currentUser, controllerDataScope.tableAlias() , controllerDataScope.userAlias());
                    }
                } else{
                    params.put("name", " AND a.name = 'have no dept , please check it' ");
                }
            }
        }
    }


    /**
     * 数据范围过滤
     *
     * @param params      当前传入数据
     * @param deptAlias 机构表别名，多个用“,”逗号隔开。
     * @param userAlias 用户表别名，多个用“,”逗号隔开，传递空，忽略此参数
     * @return 标准连接条件对象
     */
    public static void dataScopeFilter(Map<String, Object> params, User user, String deptAlias, String userAlias) {

        StringBuilder sqlString = new StringBuilder();

        // 进行权限过滤，多个角色权限范围之间为或者关系。
        List<String> dataScope = Lists.newArrayList();
        // 超级管理员，跳过权限过滤
        if (user.getUserId() != 1l) {
            boolean isDataScopeAll = false;
            for (Role r : user.getRoleList()) {
                for (String d : StringUtils.split(deptAlias, ",")) {
                    if (!dataScope.contains(r.getDataScope()) && StringUtils.isNotBlank(d)) {
                        Dept dept = user.getDept();
                        if (Role.DATA_SCOPE_ALL.equals(r.getDataScope())) {
                            isDataScopeAll = true;
                        }
//                        else if (Role.DATA_SCOPE_COMPANY_AND_CHILD.equals(r.getDataScope())){
//                            sqlString.append(" OR " + d + ".dept_id = '" + company.getDeptId() + "'");
//                            sqlString.append(" OR " + d + ".parent_ids LIKE '" + company.getParentIds() + company.getDeptId() + ",%'");
//                        }
//                        else if (Role.DATA_SCOPE_COMPANY.equals(r.getDataScope())){
//                            sqlString.append(" OR " + d + ".id = '" + company.getId() + "'");
//                            // 包括本公司下的部门 （type=1:公司；type=2：部门）
//                            sqlString.append(" OR (" + d + ".parent_id = '" + company.getId() + "' AND " + d + ".type = '2')");
//                        }
                        else if (Role.DATA_SCOPE_OFFICE_AND_CHILD.equals(r.getDataScope())) {
                            sqlString.append(" OR " + d + ".dept_id = '" + dept.getDeptId() + "'");
                            sqlString.append(" OR " + d + ".parent_ids LIKE '" + dept.getParentIds() + dept.getDeptId() + ",%'");
                        } else if (Role.DATA_SCOPE_OFFICE.equals(r.getDataScope())) {
                            sqlString.append(" OR " + d + ".dept_id = '" + dept.getDeptId() + "'");
                        } else if (Role.DATA_SCOPE_CUSTOM.equals(r.getDataScope())) {
//							String officeIds =  StringUtils.join(r.getOfficeIdList(), "','");
//							if (StringUtils.isNotEmpty(officeIds)){
//								sqlString.append(" OR " + d + ".dept_id IN ('" + officeIds + "')");
//							}
                            sqlString.append(" OR EXISTS (SELECT 1 FROM sys_role_dept WHERE role_id = '" + r.getId() + "'");
                            sqlString.append(" AND dept_id = " + d + ".dept_id)");
                        }
                        //else if (Role.DATA_SCOPE_SELF.equals(r.getDataScope())){
                        dataScope.add(r.getDataScope());
                    }
                }
            }
            // 如果没有全部数据权限，并设置了用户别名，则当前权限为本人；如果未设置别名，当前无权限为已植入权限
            if (!isDataScopeAll) {
                if (StringUtils.isNotBlank(userAlias)) {
                    for (String ua : StringUtils.split(userAlias, ",")) {
                        sqlString.append(" OR " + ua + ".user_id = '" + user.getUserId() + "'");
                    }
                } else {
                    for (String d : StringUtils.split(deptAlias, ",")) {
                        sqlString.append(" OR " + d + ".dept_id IS NULL");
                    }
                }
            } else {
                // 如果包含全部权限，则去掉之前添加的所有条件，并跳出循环。
                sqlString = new StringBuilder();
            }
        }
        if (StringUtils.isNotBlank(sqlString.toString())) {
//            Map<String , Object> params = (Map<String , Object>) joinPoint.getArgs()[0];
            params.put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
        }
//        if (StringUtils.isNotBlank(sqlString.toString())) {
//            return " AND (" + sqlString.substring(4) + ")";
//        }
//        return "";
    }

    /**
     * 数据范围过滤
     *
     * @param params 切点
     * @param user   用户
     * @param alias  别名
     */
    public static void dataScopeFilter(Map<String, Object> params, User user, String alias) {
        StringBuilder sqlString = new StringBuilder();
        for (Role role : user.getRoleList()) {
            String dataScope = role.getDataScope();
            if (DATA_SCOPE_ALL.equals(dataScope)) {
                sqlString = new StringBuilder();
                break;
            } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
//                sqlString.append(StringUtils.format(
//                        " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", alias,
//                        role.getRoleId()));
                sqlString.append(StringUtils.format(
                        " OR {}.parent_ids LIKE  CONCAT( d.parent_ids,'%') ", alias,
                        role.getRoleId()));
            }
        }

        if (StringUtils.isNotBlank(sqlString.toString())) {
//            Map<String , Object> params = (Map<String , Object>) joinPoint.getArgs()[0];
            params.put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
        }
    }

    /**
     * 是否存在注解，如果存在就获取
     */
    private DataScope getAnnotationLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (method != null) {
            return method.getAnnotation(DataScope.class);
        }
        return null;
    }

    public static Map<String , Object> limitFormat(Map<String , Object> params){
        if(params.containsKey("offset") && params.containsKey("limit")){
            String offset = params.get("offset").toString();
            String limit = params.get("limit").toString();
            params.put("offset" , Integer.parseInt(offset));
            params.put("limit" , Integer.parseInt(limit));
        }else{
            params.remove("offset");
            params.remove("limit");
        }
        return  params;
    }
}
